#include ".\ourmodel.h"
using std::vector;

#include "OurObject.h"
#include "Matrix3D.h"
#include "stdafx.h"
#include "MemDC.h"
#include <iostream>
#include <set>
#include <list>
#include <assert.h>
#include <cmath>

OurModel::OurModel():m_dbSumXcoord(0.0),m_dbSumYcoord(0.0),m_dbSumZcoord(0.0),
m_nNumOfPoints(0),m_dbMaxXcoord(0.0),m_dbMaxYcoord(0.0),m_dbMaxZcoord(0.0),
m_dbMinXcoord(0.0),m_dbMinYcoord(0.0),m_dbMinZcoord(0.0),m_bIsChanged(false),
m_ShadingMethod(FLAT),m_ViewVector(1,4,true),m_nMaxRed(0),m_nMaxGreen(0),
m_nMaxBlue(0)
{
	m_ViewVector[0][0] = 0;
	m_ViewVector[0][1] = 0;
	m_ViewVector[0][2] = 1;


}

OurModel::~OurModel(void) 
{
	clear();
}

void OurModel::clear (void) 
{
	for (vector<OurObject*>::iterator it(m_objects.begin()) ; it != m_objects.end() ; ++it)
		delete *it;
	m_objects.clear();
	m_dbSumXcoord=0.0;
	m_dbSumYcoord=0.0;
	m_dbSumZcoord=0.0;
	m_nNumOfPoints=0;
	m_dbMaxXcoord=0.0;
	m_dbMaxYcoord=0.0;
	m_dbMaxZcoord=0.0;
	m_dbMinXcoord=0.0;
	m_dbMinYcoord=0.0;
	m_dbMinZcoord=0.0;
	SetChanged(false);
}

void OurModel::reset(void)
{
	for (unsigned i=0; i<m_objects.size() ; i++)
	{	
		m_objects[i]->reset();
	}
	SetChanged(false);
}

void OurModel::paint (CMemDC &memDC,bool bDrawBoundingBox,bool bDrawAxes,bool bDrawFaceNormals,bool bDrawVertexNormals) 
{
	cout<<"m_objects.size = "<<m_objects.size()<<endl;
	for (unsigned i=0; i<m_objects.size() ; i++)
	{	
		m_objects[i]->paint(memDC,bDrawBoundingBox,bDrawAxes,bDrawFaceNormals,bDrawVertexNormals);
	}
}

OurObject *OurModel::createObject () {
	OurObject *newObj = new OurObject(this);
	m_objects.push_back(newObj);
	return newObj;
}

void OurModel::MultiplyWithMatrix(const Matrix3D& m)
{
	SetChanged(true);
	for (unsigned i=0; i<m_objects.size() ; i++)
	{	
		m_objects[i]-> MultiplyWithMatrix(m);
	}
}

Matrix3D OurModel::TranslateCenterOfMassToOrigin()
{
	Matrix3D TranslateCenterMatrix = 
		Matrix3D::TranslateMatrix(-m_dbSumXcoord/m_nNumOfPoints,
								  -m_dbSumYcoord/m_nNumOfPoints,
								  -m_dbSumZcoord/m_nNumOfPoints);
	return TranslateCenterMatrix;
}

double OurModel::GetCapacity()
{
	return (m_dbMaxXcoord-m_dbMinXcoord)*
		   (m_dbMaxYcoord-m_dbMinYcoord)*
		   (m_dbMaxZcoord-m_dbMinZcoord);
}

double OurModel::GetArea()
{
	return (m_dbMaxXcoord-m_dbMinXcoord)*
		   (m_dbMaxYcoord-m_dbMinYcoord);
}

void OurModel::SetColor(int nWireColor)
{
	for (unsigned i=0; i<m_objects.size() ; i++)
	{	
		m_objects[i]-> SetColor(nWireColor);
	}
}

bool OurModel::IsChanged() const
{
	return m_bIsChanged;
}

void OurModel::SetChanged(bool bIsChanged)
{
	m_bIsChanged = true;
}



class EdgeLess
{
public:
	bool operator()(const pair<Matrix3D,Matrix3D>& v1,const pair<Matrix3D,Matrix3D>& v2)
	{
		return min(v1.first[0][2],v1.second[0][2]) < min(v2.first[0][2],v2.second[0][2]);
	}
};

class EdgeComparator
{
public:
	bool operator()(const pair<Matrix3D*,Matrix3D*>& v1,
					const pair<Matrix3D*,Matrix3D*>& v2)
	{

		if((*v1.first)[0][0] < (*v2.first)[0][0])
			return true;
		if((*v1.first)[0][0] > (*v2.first)[0][0])
			return false;

		if((*v1.first)[0][1] < (*v2.first)[0][1])
			return true;
		if((*v1.first)[0][1] > (*v2.first)[0][1])
			return false;

		if((*v1.first)[0][2] < (*v2.first)[0][2])
			return true;
		if((*v1.first)[0][2] > (*v2.first)[0][2])
			return false;


		if((*v1.second)[0][0] < (*v2.second)[0][0])
			return true;
		if((*v1.second)[0][0] > (*v2.second)[0][0])
			return false;

		if((*v1.second)[0][1] < (*v2.second)[0][1])
			return true;
		if((*v1.second)[0][1] > (*v2.second)[0][1])
			return false;

		if((*v1.second)[0][2] < (*v2.second)[0][2])
			return true;
		if((*v1.second)[0][2] > (*v2.second)[0][2])
			return false;
		
		return false;
	}
};

class PointXComparator
{
public:
	bool operator()(const Matrix3D& p1,const Matrix3D& p2)
	{
		if(p1[0][0] < p2[0][0])
		{
			return true;
		}
		return false;
	}
};

void swap(int& n1,int& n2)
{
	int temp = n1;
	n1 = n2;
	n2 = temp;
}

int OurModel::FindIntersection(int x1,int x2,int y1,int y2,int nY)
{
	bool steep = (abs(y2-y1) > abs(x2-x1));

	if(steep)
	{
		swap(x1,y1);
		swap(x2,y2);
	}
	if (x1>x2)
	{
		swap(x1,x2);
		swap(y1,y2);
	}

	int deltax = x2 - x1;
	int deltay = abs(y2 - y1);
	int error = -(deltax + 1)/2;
	int y = y1;
	int ystep = (y1<y2)? 1 : -1;

	for (int x = x1 ; x <= x2 ; x++)
	{
		if (steep)
		{
			if (x == nY)
			{
				return y;
				break;
			}
		} 
		else
		{
			if (y == nY)
			{
				return x;
			}
		}
		error = error + deltay;
		if (error >= 0)
		{
			y = y + ystep;
			error = error - deltax;
		}
	}
	return -1;
}

double OurModel::CalculateValues(pair<Matrix3D*,Matrix3D*>& edge,
					   Polygon& p,
					   int nFirstVertex,
					   int nSecondVertex,
					   int x,
					   int y,
					   Matrix3D& Color,
					   Matrix3D& Normal)
{
	double x1 = (*edge.first)[0][0];
	double x2 = (*edge.second)[0][0];
	double y1 = (*edge.first)[0][1];
	double y2= (*edge.second)[0][1];

	double t = (abs(x2-x1) > abs(y2-y1)) ? 
			   ((double)(x-x1))/(x2-x1) : ((double)(y-y1))/(y2-y1);
	if(t>1)
	{
		t=1;
	}
	
	Matrix3D zv = ((*edge.first) * (1-t)) + ((*edge.second) * t);
	if(m_ShadingMethod == GOURAUD)
	{
		Matrix3D FirstVertexColor = p.first.first->GetGouraudColor(nFirstVertex);
		Matrix3D SecondVertexColor = p.first.first->GetGouraudColor(nSecondVertex);

		Color = (FirstVertexColor*(1-t)) + (SecondVertexColor*t);
	}
	if(m_ShadingMethod == PHONG)
	{
		Matrix3D FirstVertexNormal = p.first.first->GetVertexNormal(nFirstVertex);
		Matrix3D SecondVertexNormal = p.first.first->GetVertexNormal(nSecondVertex);

		Normal = (FirstVertexNormal*(1-t)) + (SecondVertexNormal*t);
		Normal.Normalize(1.0);
		if(Normal[0][2] < 0)
		{
			cout<<"break"<<endl;
		}
	}
	
	return zv[0][2];
}

int OurModel::GetVertexIndex(Polygon& Face,unsigned IndexInPolygon)
{
	OurObject* obj = Face.first.first;
	return obj->GetVertexIndex(Face.first.second,IndexInPolygon);
}


void OurModel::ScanLine(Polygon& Face,
						vector<pair<double,Matrix3D> >& ZBuffer,
						int y,
						int nScreenXmin,
						vector<pair<Matrix3D,bool> >& LightSources,
						vector<Matrix3D>& LightSourcesIntensity,
						Matrix3D& AmbientIntensity)
{
	//multiset<pair<Matrix3D*,Matrix3D*>,EdgeComparator> ActiveEdges;
	//assumption: the last vertex is the first vertex
	vector<pair<unsigned,unsigned> > ActiveEdges;
	
	for(unsigned i=0;i<Face.second.size()-1;i++)
	{
		Matrix3D& Face1 = *(Face.second[i]);
		Matrix3D& Face2 = *(Face.second[(i+1) % (Face.second.size())]);

		if(min(Matrix3D::roundInt(Face1[0][1]),
			   Matrix3D::roundInt(Face2[0][1])) <= y &&
		   max(Matrix3D::roundInt(Face1[0][1]),
			   Matrix3D::roundInt(Face2[0][1])) >= y)
		{
			/*ActiveEdges.insert(
				pair<Matrix3D*,Matrix3D*>(Face.second[i],
				Face.second[(i+1) % (Face.second.size())]));*/
			ActiveEdges.push_back(pair<unsigned,unsigned>(i,(i+1) % (Face.second.size())));
		}
	}

	int xMin = 32767;
	int xMax = -32767;
	Matrix3D xMinColor;
	Matrix3D xMaxColor;
	Matrix3D xMinNormal(1,4,true);
	Matrix3D xMaxNormal(1,4,true);
	double zMin;
	double zMax;
	/*for(multiset<pair<Matrix3D*,Matrix3D*>,EdgeComparator>::iterator itActiveEdge = 
			ActiveEdges.begin();
		itActiveEdge != ActiveEdges.end();
		itActiveEdge ++)*/
	for(unsigned i=0;i<ActiveEdges.size();i++)
	{
		Matrix3D* v1 = Face.second[ActiveEdges[i].first];
		Matrix3D* v2 = Face.second[ActiveEdges[i].second];
		pair<Matrix3D*,Matrix3D*> e(v1,v2);

		int x1 = Matrix3D::roundInt((*e.first)[0][0]);
		int x2 = Matrix3D::roundInt((*e.second)[0][0]);
		int y1 = Matrix3D::roundInt((*e.first)[0][1]);
		int y2 = Matrix3D::roundInt((*e.second)[0][1]);
		int xx;

		xx = FindIntersection(x1,x2,y1,y2,y);	
		if (xx < (xMin))
		{
			xMin = xx;
			int nFirstVertexIndex = GetVertexIndex(Face,ActiveEdges[i].first);
			int nSecondVertexIndex = GetVertexIndex(Face,ActiveEdges[i].second);
			zMin = 
				CalculateValues(
				e,Face,nFirstVertexIndex,nSecondVertexIndex,xx,y,xMinColor,xMinNormal);
		}
		if (xx > (xMax)) 
		{
			xMax = xx;
			int nFirstVertexIndex = GetVertexIndex(Face,ActiveEdges[i].first);
			int nSecondVertexIndex = GetVertexIndex(Face,ActiveEdges[i].second);
			zMax = 
				CalculateValues(
				e,Face,nFirstVertexIndex,nSecondVertexIndex,xx,y,xMaxColor,xMaxNormal);
		}
		xx = FindIntersection(x1,x2,y2,y1,y);
		xx = x1+x2-xx; 
			//Matrix3D::roundInt(((*e.first)[0][0]+(*e.second)[0][0]) - xx);

		if (xx < (xMin))
		{
			xMin = xx;
			int nFirstVertexIndex = GetVertexIndex(Face,ActiveEdges[i].first);
			int nSecondVertexIndex = GetVertexIndex(Face,ActiveEdges[i].second);
			zMin = 
				CalculateValues(
				e,Face,nFirstVertexIndex,nSecondVertexIndex,xx,y,xMinColor,xMinNormal);
		}
		if (xx > (xMax)) 
		{
			xMax = xx;
			int nFirstVertexIndex = GetVertexIndex(Face,ActiveEdges[i].first);
			int nSecondVertexIndex = GetVertexIndex(Face,ActiveEdges[i].second);
			zMax = 
				CalculateValues(
				e,Face,nFirstVertexIndex,nSecondVertexIndex,xx,y,xMaxColor,xMaxNormal);
		}
	}

	OurObject* FaceObject = Face.first.first;
	unsigned PolygonIndex = Face.first.second;

	for(int x= xMin;x<=xMax;x++)
	{	
		double t = (xMin == xMax)? 1:(1.0*(x-xMin))/(xMax-xMin);
		double z = (1-t)*zMin +t*zMax;

		if(x-nScreenXmin+1 >= ZBuffer.size())
		{
			break;
		}
		if(z<=ZBuffer[x-nScreenXmin+1].first)
		{
			Matrix3D Color;
			if(m_ShadingMethod == GOURAUD)
			{
				Color = (xMinColor*(1-t))+(xMaxColor*t);
			}
			if(m_ShadingMethod == FLAT)
			{
				Color = Face.first.first->GetFlatColor(Face.first.second);
			}
			if(m_ShadingMethod == PHONG)
			{
				Matrix3D Normal = (xMinNormal*(1-t))+(xMaxNormal*t);
				Matrix3D point(1,4,true);
				point[0][0] = x;
				point[0][1] = y;
				point[0][2] = z;
				OurObject* obj = Face.first.first;

				Color = OurObject::CalculateColor( 
										point,
										obj->GetKa(Face.first.second),
										obj->GetKd(Face.first.second),
										obj->GetKs(),
										m_ViewVector,
										LightSources,
										Normal,
										AmbientIntensity,
										LightSourcesIntensity,
										obj->GetN(),
										m_dbAmbient,
										m_dbDiffuse,
										m_dbSpecular,
										m_nCosineFactor);
			}
			ZBuffer[x-nScreenXmin+1] = 
				pair<double,Matrix3D>(z,Color);
		}
	}
}

class FacesetComparator
{
public:
	bool operator()(const vector<Matrix3D>& f1,const vector<Matrix3D>& f2)
	{
		if(f1.size()<f2.size())
			return true;
		if(f1.size()>f2.size())
			return false;
		
		for(unsigned i=0;i<f1.size();i++)
		{
			for(unsigned j=0;j<3;j++)
			{
				if(f1[i][0][j] < f2[i][0][j])
				{
					return true;
				}
				if(f1[i][0][j] > f2[i][0][j])
				{
					return false;
				}
			}
		}
		return false;
	}
};

int OurModel::MinYInFaceset(const Polygon& face)
{
	double dbYmin = (*face.second[0])[0][1];
	for (unsigned i=1;i<face.second.size();i++)
	{
		dbYmin = min(dbYmin,(*face.second[i])[0][1]);
	}
	return Matrix3D::roundInt(dbYmin);
}

int OurModel::MaxYInFaceset(const Polygon& face)
{
	double dbYmax =  (*face.second[0])[0][1];
	for (unsigned i=1;i<face.second.size();i++)
	{
		dbYmax = max(dbYmax,(*face.second[i])[0][1]);
	}
	return Matrix3D::roundInt(dbYmax);
}

void OurModel::ZBufferScanLine(CMemDC& memDC,
							   int nRectYmin,
							   int nRectYmax,
							   int nRectXmin,
							   int nRectXmax,
							   double dbRectZMax,
							   double dbRectZMin,
							   int nBackgroundR,int nBackgroundG,int nBackgroundB,
							   vector<pair<Matrix3D,bool> >& LightSources,
							   vector<Matrix3D>& LightSourcesIntensity,
							   Matrix3D& AmbientIntensity)
{
	//assumption: the scene was already projected
	//1. collecting all the faces from all the objects into one multiset
	//	 that is sorted by the Ymin of the facesets.
	//

	int nScreenYmin = nRectYmax;
	int nScreenYmax = nRectYmin;
	int nScreenXmin = nRectXmax;
	int nScreenXmax = nRectXmin;

	double dbScreenZMax = dbRectZMin;
	double dbScreenZMin = dbRectZMax;
	multiset<Polygon,FacesetYComparator> SortedFaces;
	for (unsigned i=0; i<m_objects.size() ; i++)
	{	
		m_objects[i]->AddFaces(SortedFaces,
								nScreenYmin,
								nScreenYmax,
								nScreenXmin,
								nScreenXmax,
								dbScreenZMax,
								dbScreenZMin);
		/*if(i==0)
		{
			nScreenYmin = m_objects[i]->GetMinY();
			nScreenYmax = m_objects[i]->GetMaxY();
			nScreenXmin = m_objects[i]->GetMinX();
			nScreenXmax = m_objects[i]->GetMaxX();
			
			dbScreenZMax = m_objects[i]->GetMaxZ();
			dbScreenZMin = m_objects[i]->GetMinZ();
		}
		else
		{
			nScreenYmax = max(nScreenYmax,m_objects[i]->GetMaxY());
			nScreenYmin = min(nScreenYmin,m_objects[i]->GetMinY());
			nScreenXmax = max(nScreenXmax,m_objects[i]->GetMaxX());
			nScreenXmin = min(nScreenXmin,m_objects[i]->GetMinX());

			dbScreenZMax = max(dbScreenZMax,m_objects[i]->GetMaxZ());
			dbScreenZMin = min(dbScreenZMin,m_objects[i]->GetMinZ());
		}	*/
		if(m_ShadingMethod == FLAT)
		{
			m_objects[i]->
				SetFlatColorOfFaces(LightSources,
									LightSourcesIntensity,
									AmbientIntensity,
									m_ViewVector,
									m_dbAmbient,
									m_dbDiffuse,
									m_dbSpecular,
									m_nCosineFactor);
		}
		if(m_ShadingMethod == GOURAUD)
		{
			m_objects[i]->
				SetGouraudColorsForVertices(LightSources,
											LightSourcesIntensity,
											AmbientIntensity,
											m_ViewVector,
											m_dbAmbient,
											m_dbDiffuse,
											m_dbSpecular,
											m_nCosineFactor);
		}
	}
	if(SortedFaces.size() == 0)
		return;
	


	list<Polygon*> ActiveFaces;

	multiset<Polygon,FacesetYComparator>::iterator 
											itFaces = SortedFaces.begin();

	m_Scene.clear();
	for(int y=nScreenYmin;y<=nScreenYmax;y++)
	{
		while(itFaces != SortedFaces.end())
		{
			Polygon& f = (*itFaces);
			if(MinYInFaceset(f) <= y)
			{
				if(MaxYInFaceset(f) >= y)
				{
					ActiveFaces.push_back(&f);
				}
				itFaces++;
			}
			else
			{
				break;
			}
		}
		/*
		for(list<Polygon*>::iterator itActiveFaces = ActiveFaces.begin();
			itActiveFaces != ActiveFaces.end();)
		{
			Polygon& f = *(*itActiveFaces);
			if(MaxYInFaceset(f) < y)
			{
				itActiveFaces = ActiveFaces.erase(itActiveFaces);
			}
			else
			{
				itActiveFaces++;
			}
		}
		*/
		if(ActiveFaces.empty())
		{
			continue;
		}
		
		//maps points x to (z,color)
		vector<pair<double,Matrix3D> > ZBuffer;
		/*for(int x=nScreenXmin-1;x<=nScreenXmax+1;x++)
		{
			
		}*/

		Matrix3D BackColor(4,4,true);
		BackColor[0][0] = nBackgroundR;
		BackColor[1][1] = nBackgroundG;
		BackColor[2][2] = nBackgroundB;
		ZBuffer.resize(nScreenXmax-nScreenXmin+2,pair<double,Matrix3D>(dbScreenZMax+1,BackColor));


		for(list<Polygon*>::iterator itActiveFaces =
				ActiveFaces.begin();
			itActiveFaces != ActiveFaces.end();
			itActiveFaces++)
		{
			 Polygon& Face = *(*itActiveFaces);
	
			//assumption: the face is convex
			ScanLine(Face,
					 ZBuffer,
					 y,
					 nScreenXmin,
					 LightSources,
					 LightSourcesIntensity,
					 AmbientIntensity);
		}
		EmptyZBufferToScene(nScreenYmin,nScreenXmin,ZBuffer);
	}	
	paintRendered(memDC);
}

void OurModel::paintRendered(CMemDC& memDC)
{
	CPen pen(PS_SOLID,1,RGB(0,0,0));
	CPen *oldPen = memDC.SelectObject(&pen);
	
	int nMaxColorPart = max(m_nMaxRed,max(m_nMaxGreen,m_nMaxBlue));

	if(nMaxColorPart > 255)
	{
		for(unsigned i=0;i<m_Scene.size();i++)
		{
			for(unsigned j=0;j<m_Scene[i].size();j++)
			{
				m_Scene[i][j] *= (255.0/nMaxColorPart);
			}
		}
	}

	for(unsigned i=0;i<m_Scene.size();i++)
	{
		for(unsigned j=0;j<m_Scene[i].size();j++)
		{
			Matrix3D& color = m_Scene[i][j];
			int nColor = RGB(static_cast<int>(color[0][0]),
							static_cast<int>(color[1][1]),
							static_cast<int>(color[2][2]));

			memDC.SetPixel(j+m_nSceneXmin-1,i+m_nSceneYmin-1,nColor);
			
		}
	}

	memDC.SelectObject(oldPen);
}

void OurModel::BackFaceCulling(bool bIsOn,bool bNormalSwitchDirection)
{
	for(unsigned i=0;i<m_objects.size();i++)
	{
		m_objects[i]->BackFaceCulling(bIsOn,bNormalSwitchDirection);
	}
}



void OurModel::SetShadingMethod(ShadingMethod eMethod)
{
	m_ShadingMethod = eMethod;
}
/*
Matrix3D OurModel::CalculateColor( 
							  Matrix3D& CenterOfFace,
						      Matrix3D& Ka,
							  Matrix3D& Kd,
							  Matrix3D& Ks,
							  Matrix3D& ViewVector,
							  vector<pair<Matrix3D,bool> >& LightVectors,
							  Matrix3D& SurfaceNormal,
							  Matrix3D& AmbientIntensity,
							  vector<Matrix3D>& LightSourcesIntensity,
							  int nShininess)
{
	int nR;
	int nG;
	int nB;

	//the ambient part

	
	//Matrix3D Result = Ka*AmbientIntensity;
	Matrix3D Result = Ka*AmbientIntensity*(m_dbAmbient);

	assert(LightVectors.size() == LightSourcesIntensity.size());
	
	Matrix3D DiffuseSum(4,4,true);
	Matrix3D ReflectionSum(4,4,true);
	for(unsigned l=0;l<LightVectors.size();l++)
	{
		Matrix3D LightVector(1,4,true);
		if(LightVectors[l].second == true)
		{
			//is point source, we should calculate the direction
			LightVector = CenterOfFace-LightVectors[l].first;
			LightVector.Normalize(1.0);
		}
		else
		{
			LightVector = LightVectors[l].first;
		}
		//the diffuse part
		double NL = 0;
		for(unsigned i=0;i<3;i++)
		{
			NL+= SurfaceNormal[0][i] * (-LightVector[0][i]);
		}
		if(NL<0)
		{
			NL=0;
			continue;
		}
		else
		{
			cout<<"yippie";
		}

		DiffuseSum += (LightSourcesIntensity[l]*NL);

		//the reflection part
		double RV = 0;
		Matrix3D ReflectionVector = ((SurfaceNormal*(2*NL))+LightVector);
		//Matrix3D ReflectionVector = LightVectors[l];
		//ReflectionVector+= ((SurfaceNormal - LightVectors[l])*2);
		//ReflectionVector.Normalize(1.0);
		for(unsigned i=0;i<3;i++)
		{
			RV += ReflectionVector[0][i]*(ViewVector[0][i]*(-1.0));
		}
		if(RV<0)
		{
			RV=0;
		}
		RV = pow(RV,nShininess*m_nCosineFactor);
		ReflectionSum += (LightSourcesIntensity[l]*RV);
	}
	Result += Kd*DiffuseSum*(m_dbDiffuse);
	Result += Ks*ReflectionSum*(m_dbSpecular);

	if(Result[0][0] < 0 || Result[1][1] < 0 || Result[2][2] < 0)
	{
		Result = Matrix3D(4,4,true);
	}

	return Result;
}*/

void OurModel::EmptyZBufferToScene(int nYmin,int nXmin,vector<pair<double,Matrix3D> >& ZBuffer)
{
	m_nSceneXmin = nXmin;
	m_nSceneYmin = nYmin;
	m_Scene.push_back(vector<Matrix3D>());
	unsigned nLast = m_Scene.size()-1;
	for(unsigned i=0;i<ZBuffer.size();i++)
	{
		Matrix3D& color = ZBuffer[i].second;
		m_Scene[nLast].push_back(ZBuffer[i].second);
		if(color[0][0] > m_nMaxRed)
		{
			m_nMaxRed = color[0][0];
		}
		if(color[0][0] > m_nMaxGreen)
		{
			m_nMaxGreen = color[1][1];
		}
		if(color[0][0] > m_nMaxBlue)
		{
			m_nMaxBlue = color[2][2];
		}
	}
	
}

double OurModel::GetAmbientFactor()
{
	return m_dbAmbient;
}
double OurModel::GetDiffuseFactor()
{
	return m_dbDiffuse;
}
double OurModel::GetSpecularFactor()
{
	return m_dbSpecular;
}
double OurModel::GetCosineFactor()
{
	return m_nCosineFactor;
}

void OurModel::SetAmbientFactor(double dbAmbient)
{
	m_dbAmbient = dbAmbient;
}
void OurModel::SetDiffuseFactor(double dbDiffuse)
{
	m_dbDiffuse = dbDiffuse;
}
void OurModel::SetSpecularFactor(double dbSpecular)
{
	m_dbSpecular = dbSpecular;
}
void OurModel::SetCosineFactor(int nCosine)
{
	m_nCosineFactor = nCosine;
}

OurModel::ShadingMethod OurModel::GetShadingMethod()
{
	return m_ShadingMethod;
}

